A computer program is usually written in a language other than the machine language used by the computer to execute the program. The reason is that machine language is not designed for human communication. Because computers utilize two-state storage and switching devices, sequences of binary digits provide the most natural form for expressing program instructions. However, sequences of binary digits are very unnatural for humans to construct or to understand.
The language in which a computer program is written is called source code. A translator is used to translate the source code into machine language understandable by the computer. In some systems, a first translator translates the source code into an intermediate language, such as an assembly language, and a second translator translates the intermediate language into machine language.
There are two basic types of translators: compilers and interpreters. Compilers translate an entire source code program into an object code program that is executed some time later. In contrast, interpreters translate and execute one instruction of a program before translating and executing the next instruction of the program. As such, interpreters do not produce any object code. Compiled programs execute much faster than interpreted programs, resulting in most programs of greater than slight complexity being compiled programs. Interpreted programs have the advantage of being flexible, in that the programs do not have to be recompiled each time a change is made to the program.
Some programs are compiled into an intermediate language known as pseudocode. Pseudocode is executed by a software interpreter which can be referred to as the pseudocode execution engine. The pseudocode execution engine translates and executes program instructions by repeatedly executing a routine known as an interpretive loop. The interpretive loop includes four basic steps:
1. Fetch a pseudocode instruction from a position specified by an instruction counter; PA1 2. Increment the instruction counter; PA1 3. Analyze the fetched instruction to determine what operation is to be performed and the operands for the operation; and PA1 4. Execute the instruction by calling a subroutine for performing the specified operation.
During execution of the interpretive loop, the execution engine uses a stack pointer register, an accumulator register, and possibly other registers of the computer in addition to the instruction counter. The contents of such registers at any time during execution of the interpretive loop are collectively known as the state of the execution engine.
Like most programs, the execution engine interacts with a computer operating system to access hardware devices of the computer. Most advanced operating systems, such as the Microsoft Windows operating system and OS/2, are event- or message-based multitasking systems. In such event-based systems, the user interacts with windows, menus, and controls in a user interface of a program. User-generated events, such as mouse clicks and keystrokes, place "messages" in the program's message queue. The program uses a message loop to get messages from the queue and send the messages to the appropriate window for handling by a window procedure. Each window is associated with a window procedure that responds to the messages received from the message loop. Alternatively, messages can be sent directly from an operating system routine to the window procedure without using the message queue if the operating system routine is given a pointer to the window procedure.
The window procedure is a type of routine known as a callback routine. In general, a callback routine is a routine that receives messages or other information from another routine, such as an operating system routine. The information received can be asynchronous relative to the execution of the callback routine, that is, the information is received at unexpected times. System interrupts and messages received based on user input, i.e. window messages, are examples of asynchronous information. The information received also can be synchronous, that is, information received according to a synchronous execution of instructions. Synchronous information results when a program calls a routine, such as an operating system routine and tells the operating system routine to "call back" to a callback routine in the program. The call back to the callback routine passes information produced by execution of the operating system routine.
Callback routines are used extensively by event-based operating systems, such as the Microsoft Windows operating system. The callback routine arrangement works fine if the program and callback routine are compiled into machine language. However, the callback routine arrangement provided by the Windows operating system does not work for non-machine language pseudocode programs. That is because, unlike the Windows callback routines, a pseudocode program does not have a machine address that can be supplied to the operating system to enable it to find a callback routine within the program.
The Basic language is a well-known example of a source language that typically is compiled into pseudocode and executed by a software interpreter. The Basic language is a relatively simple language and therefore is a popular choice for programmers when writing programs. Such popularity and ease of use creates a need for a system that could provide a pseudocode program, such as a program written in Basic, with the callback capabilities found in the Windows operating system